import javax.sound.sampled.*;
import java.util.*;
import java.io.*;

public class play{
	public static void main(String args[]) throws Throwable{
		if (args.length==0)
			return;

		AudioFormat format = new AudioFormat(8000.0f, 16, 1, true, true);
		DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
		Line line = AudioSystem.getLine(info);

		if (!(line instanceof SourceDataLine)){
			System.err.println("Can't acquire audio line");
			System.exit(1);
		}

		byte[] buffer=new byte[4096];
		ByteArrayOutputStream bout = new ByteArrayOutputStream(1000000);
		int got;

		// pre-compute all of our sound data into a buffer
		for (int i=0;i<args.length;i++){
			if (args[i].equals("silent")) continue;
			if (args[i].equals("pause")) continue;
			else if (args[i].equals("blank")){
				for (int j=0;j<2500;j++){
					bout.write(0);
					bout.write(0);
				}
			}else{
				AudioInputStream ain = AudioSystem.getAudioInputStream(new File(args[i]));
				while((got=ain.read(buffer))!=-1){
					for (int j=0;j<got;j++){
						int result = ulaw2linear(buffer[j]&0xFF);
						bout.write((result>>8)&0xFF);
						bout.write(result&0xFF);
					}
				}
			}
		}

		byte[] allbytes = bout.toByteArray();
		bout=null;
		buffer=null;

		int i=0;


		/* dump our sound data to the speaker.
		   we have to do this carefully because the speakers
		   will read from the buffer in real-time, so we have
		   to make sure that the buffer is always full, while
		   at the same time not giving it too much data at once.
		*/
		SourceDataLine source = (SourceDataLine)line;
		source.open(format, 4096);
		source.start();
		while(i<allbytes.length){
			if (source.available()>0){
				int min = Math.min(source.available(), allbytes.length-i);
				source.write(allbytes,i,min);
				i+=min;
			}
		}

		// 'drain' will block until all the queued sound data has been played
		source.drain();
		source.stop();
		source.close();

		System.exit(0);
	}


	/** I stole this code, I have no idea how it works.
		Apparently it turns 8-bit mu-law samples into 16-bit
		signed PCM samples.
	*/
	private static int ulaw2linear(int ulawbyte){
		int exp_lut[] = {0,132,396,924,1980,4092,8316,16764};
		int sign, exponent, mantissa, sample;

		ulawbyte = ~ulawbyte;
		sign = (ulawbyte & 0x80);
		exponent = (ulawbyte >> 4) & 0x07;
		mantissa = ulawbyte & 0x0F;
		sample = exp_lut[exponent] + (mantissa << (exponent + 3));
		if (sign != 0) sample = -sample;

		return(sample);
	}
}
